"""
定时任务调度器 - 定期处理OCR队列中的任务
使用APScheduler库来实现定时任务功能

调度器工作机制：
1. 使用APScheduler的AsyncIOScheduler实现异步定时任务
2. 每5秒检查一次队列，处理待办任务
3. 通过间隔触发器(IntervalTrigger)实现周期性执行
4. 提供启动和关闭接口，便于应用生命周期管理
"""

# 导入标准库和第三方库
from apscheduler.schedulers.asyncio import AsyncIOScheduler  # APScheduler异步调度器
from apscheduler.triggers.interval import IntervalTrigger  # 间隔触发器，用于定时执行
import asyncio  # 异步IO库，支持异步任务执行
from typing import Optional, Dict  # 类型提示，提高代码可读性和类型安全性

# 导入项目内部模块
from tools.ocr_processor import process_one_task  # OCR任务处理函数，执行具体的OCR识别任务
from tools.redis_queue import get_queue_length  # 获取队列长度的函数，用于监控队列状态

# 创建一个异步调度器对象
# 调度器就像一个定时器，可以定期执行某个任务
# AsyncIOScheduler支持异步任务调度，与FastAPI异步框架完美集成
scheduler = AsyncIOScheduler()


async def process_ocr_queue_job():
    """
    定时任务的工作函数 - 处理OCR队列中的任务
    这个函数会被定时调用，每次调用时处理队列中的一个任务
    
    任务处理流程：
    1. 检查队列中是否有待处理任务
    2. 如果有任务，调用process_one_task处理一个任务
    3. 记录处理结果日志
    4. 如果没有任务，记录空队列状态
    
    工作流程：
    1. 检查队列中是否有任务
    2. 如果有任务，取出一个并处理
    3. 如果没有任务，什么都不做
    """
    # 获取队列中还有多少个任务
    # 通过队列长度判断是否需要执行任务处理逻辑
    queue_length = get_queue_length()
    
    # 打印日志，方便查看队列状态
    # 日志记录有助于监控系统运行状态和性能调优
    if queue_length > 0:
        print(f"[定时任务] 队列中还有 {queue_length} 个任务，开始处理...")
        
        # 调用process_one_task处理一个任务
        # 如果处理成功，返回True；如果没有任务或失败，返回False
        # 异步调用确保不会阻塞调度器的其他任务
        success = await process_one_task()
        
        # 根据处理结果显示日志
        # 成功日志便于确认任务处理正常，失败日志便于问题排查
        if success:
            print(f"[定时任务] 任务处理成功")
        else:
            print(f"[定时任务] 没有任务或处理失败")
    else:
        # 队列为空，不需要处理
        # 记录空队列状态，便于监控系统运行情况
        print(f"[定时任务] 队列为空，无需处理")


async def start_scheduler():
    """
    启动定时任务调度器
    这个函数会在应用启动时调用，开始定时执行任务
    注意：这是一个异步函数，可以在FastAPI的异步环境中正确启动
    
    启动流程：
    1. 检查调度器是否已在运行
    2. 添加OCR队列处理任务
    3. 启动调度器开始执行任务
    4. 记录启动状态日志
    """
    try:
        # 检查调度器是否已经在运行
        # 如果已经在运行，就不需要重复启动
        # 避免重复启动导致的资源浪费和状态异常
        if scheduler.running:
            print("[调度器] 调度器已经在运行中")
            return
        
        # 添加一个定时任务
        # IntervalTrigger表示间隔触发，每隔一定时间执行一次
        # seconds=5表示每5秒执行一次
        scheduler.add_job(
            func=process_ocr_queue_job,           # 要执行的函数
            trigger=IntervalTrigger(seconds=5),   # 每5秒触发一次
            id='ocr_queue_processor',             # 任务的唯一ID，用于标识和管理任务
            name='处理OCR队列任务',                # 任务的名称，便于理解和识别
            replace_existing=True                 # 如果任务已存在，替换它
        )
        
        # 启动调度器
        # 调度器启动后，就会按照设定的时间间隔执行任务
        # AsyncIOScheduler会自动使用当前的事件循环
        scheduler.start()
        
        # 打印日志，确认调度器已启动
        # 启动日志便于确认调度器正常工作
        print("[调度器] OCR队列处理定时任务已启动，每5秒执行一次")
        
    except Exception as e:
        # 如果启动过程中出错了，打印错误信息
        # 这样可以知道是什么问题，比如Redis连接失败等
        print(f"[调度器错误] 启动失败: {e}")
        # 抛出异常，让调用者知道启动失败了
        raise


async def shutdown_scheduler():
    """
    关闭定时任务调度器
    这个函数会在应用关闭时调用，停止定时任务
    注意：这是一个异步函数，可以在FastAPI的异步环境中正确关闭
    
    关闭流程：
    1. 检查调度器是否在运行
    2. 如果运行中，则执行关闭操作
    3. 等待正在运行的任务完成
    4. 记录关闭状态日志
    """
    # 检查调度器是否在运行
    # 如果不在运行，就不需要关闭
    # 避免对未运行的调度器执行关闭操作
    if not scheduler.running:
        print("[调度器] 调度器未在运行")
        return
    
    # 停止调度器
    # shutdown会等待所有正在运行的任务完成后才关闭
    # wait=True参数确保优雅关闭，避免任务中断
    scheduler.shutdown(wait=True)
    
    # 打印日志
    # 关闭日志便于确认调度器已正确停止
    print("[调度器] OCR队列处理定时任务已停止")